/**
 * 
 */

package com.chengyu.eyc.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.chengyu.eyc.base.ResponseResult;
import com.chengyu.eyc.constant.EycConstants;
import com.chengyu.eyc.entity.MsgEntity;
import com.chengyu.eyc.enums.PayStatusEnum;
import com.chengyu.eyc.enums.UserTypeEnums;
import com.chengyu.eyc.exception.GenericException;
import com.chengyu.eyc.model.EycCouponRule;
import com.chengyu.eyc.model.EycInspStation;
import com.chengyu.eyc.model.EycOrder;
import com.chengyu.eyc.model.EycOtherShop;
import com.chengyu.eyc.model.EycUser;
import com.chengyu.eyc.model.EycUserCoupon;
import com.chengyu.eyc.model.EycVehicleAv;
import com.chengyu.eyc.model.EycVehicleAvAddr;
import com.chengyu.eyc.model.EycVehicleFile;
import com.chengyu.eyc.model.EycVerPerson;
import com.chengyu.eyc.properties.EycProperties;
import com.chengyu.eyc.service.EycBaseService;
import com.chengyu.eyc.service.EycService;
import com.chengyu.eyc.service.SmsService;
import com.chengyu.eyc.service.WechatService;
import com.chengyu.eyc.utils.AESUtil;
import com.chengyu.eyc.utils.EycFileUtil;
import com.chengyu.eyc.utils.JWTUtil;
import com.chengyu.eyc.utils.QRCodeUtil;
import com.chengyu.eyc.utils.RegexUtils;
import com.chengyu.eyc.utils.SignatureUtils;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.PageInfo;

import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * @author kevin
 *
 */
@Slf4j
@RestController
@RequestMapping("wechat")
public class WechatController {

    @Autowired
    EycService eycService;

    @Autowired
    EycBaseService eycBaseService;

    @Autowired
    EycProperties eycProperties;

    @Autowired
    WechatService wechatService;

    @Autowired
    SmsService smsService;

    @Autowired
    WxPayService wxService;

    @PostMapping("applyRefund")
    public ResponseResult<EycOrder> applyRefund(@RequestBody EycOrder eycOrder) {
        eycOrder.setPayStatus(PayStatusEnum.REFUNDING.getCode());
        return ResponseResult.ok(this.eycService.updateEycOrder(eycOrder));
    }

    @PostMapping("cancelOrder")
    public ResponseResult<EycOrder> cancelOrder(@RequestBody String orderNum, @RequestHeader(name = EycConstants.TOKEN) String token) {
        String userId = JWTUtil.parseJWT(token).getId();
        return ResponseResult.ok(this.eycService.cancelOrder(orderNum, userId));
    }

    @GetMapping("incoming")
    public String checkSignature(@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce,
        @RequestParam("echostr") String echostr) {
        Boolean verify = SignatureUtils.checkSignature(signature, timestamp, nonce);
        return Boolean.TRUE.equals(verify) ? echostr : null;
    }

    @PostMapping("decryptData")
    public ResponseResult<String> decryptData(@RequestBody Map<String, Object> params) {
        AESUtil aes = new AESUtil((String)params.get("encryptedData"), (String)params.get("session_key"), (String)params.get("iv"));
        String decrypt =  aes.decrypt();
        return ResponseResult.ok(decrypt);

    }

    /**
     * 删除爱车
     * 
     * @param eycVehicleFile
     * @return
     */
    @PostMapping("deleteEycVehicleFile")
    public ResponseResult<Boolean> deleteEycVehicleFile(@RequestBody EycVehicleFile eycVehicleFile) {
        return ResponseResult.ok(this.eycService.deleteVehicleFile(eycVehicleFile));
    }

    @GetMapping("genQRCode")
    public ResponseEntity<FileSystemResource> genQRCode(@RequestParam("orderNum") String orderNum, @RequestParam(value = "logoUrl", required = false) String logoUrl) throws Exception {
        String filePath = eycProperties.getDomainName() + "/wechat/verificationOrder?orderNum=%s";
        BufferedImage bufferedImage = QRCodeUtil.genQRCode(String.format(filePath, orderNum), logoUrl);
        File outputfile = new File(this.eycProperties.getFileDir() + File.separator + "qr", orderNum + ".png");
        if (!outputfile.exists()) {
            FileUtils.forceMkdir(outputfile);
        } else {
            FileUtils.forceDelete(outputfile);
        }
        ImageIO.write(bufferedImage, "png", outputfile);
        return EycFileUtil.getResponseResource(outputfile);
    }

    @PostMapping("getAccessToken")
    public ResponseResult<String> getAccessToken(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.wechatService.getAccessToken(claims.getId()));
    }

    @PostMapping("getOpenId")
    public ResponseResult<Map<String, Object>> getOpenId(@RequestBody String code) {
        return ResponseResult.ok(this.wechatService.getOpenId(code));
    }

    @ApiOperation("车辆估值")
    @PostMapping("insertEycVehicleAv")
    public ResponseResult<EycVehicleAv> insertEycVehicleAv(@RequestBody EycVehicleAv eycVehicleAv, @RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        eycVehicleAv.setEvaluator(claims.getId());
        this.eycBaseService.insertEycVehicleAv(eycVehicleAv);
        return ResponseResult.ok(eycVehicleAv);
    }

    /**
     * 生成订单
     * 
     * @param eycOrder
     * @return
     */
    @ApiOperation("生成订单")
    @PostMapping("insertOrder")
    public ResponseResult<EycOrder> insertOrder(@RequestBody EycOrder eycOrder, @RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        eycOrder.setUserId(claims.getId());
        eycOrder.setCreatePerson(claims.getId());
        return ResponseResult.ok(this.eycService.insertOrder(eycOrder));
    }
    
    @ApiOperation("生成订单")
    @PostMapping("editOrder")
    public ResponseResult<EycOrder> editOrder(@RequestBody EycOrder eycOrder, @RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        eycOrder.setUserId(claims.getId());
        eycOrder.setUpdatePerson(claims.getId());
        return ResponseResult.ok(this.eycService.updateEycOrder(eycOrder));
    }
    
    

    @PostMapping("insertOrUpdateVehicleAvAddr")
    public ResponseResult<EycVehicleAvAddr> insertOrUpdateVehicleAvAddr(@RequestBody EycVehicleAvAddr eycVehicleAvAddr, @RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        eycVehicleAvAddr.setUserId(claims.getId());
        eycVehicleAvAddr.setCreatePerson(claims.getId());
        return ResponseResult.ok(this.eycBaseService.insertOrUpdateVehicleAvAddr(eycVehicleAvAddr));
    }

    /**
     * 添加或修改爱车信息
     * 
     * @param eycVehicleFile
     * @return
     */
    @PostMapping("insertOrUpdateVehicleFile")
    public ResponseResult<EycVehicleFile> insertOrUpdateVehicleFile(@RequestBody EycVehicleFile eycVehicleFile, @RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        eycVehicleFile.setUserId(claims.getId());
        eycVehicleFile.setCreatePerson(claims.getId());
        return ResponseResult.ok(this.eycService.insertOrUpdateVehicleFile(eycVehicleFile));
    }

    @PostMapping("insertUser")
    public ResponseResult<EycUser> insertUser(EycUser eycUser) {
        eycUser.setUserType(UserTypeEnums.OUTER_USER.getCode());
        eycUser = this.eycService.insertUser(eycUser);
        return ResponseResult.ok(eycUser);
    }

    @PostMapping("isLogin")
    public ResponseResult<Boolean> isLogin(@RequestHeader(name = EycConstants.TOKEN) String token) {
        if (StrUtil.isNotBlank(token)) {
            return ResponseResult.ok(JWTUtil.validateJWT(token));
        }
        return ResponseResult.ok(Boolean.FALSE);
    }

    @PostMapping("obtainMiniUserInfo")
    public ResponseResult<Map<String, Object>> obtainMiniUserInfo(@RequestBody String openid) {
        return ResponseResult.ok(this.wechatService.getUserInfo(this.wechatService.getAccessToken(openid), openid));
    }

    @PostMapping("obtainOfficialAccountUserInfo")
    public ResponseResult<Map<String, Object>> obtainOfficialAccountUserInfo(@RequestBody String openid) {
        return ResponseResult.ok(this.wechatService.getUserInfo(this.wechatService.getOfficialAccountAccessToken(), openid));
    }

    @PostMapping("obtainVehicleLicenseInfo")
    public ResponseResult<Map<String, Object>> obtainVehicleLicenseInfo(@RequestBody Map<String, String> map) {
        return ResponseResult.ok(this.wechatService.obtainVehicleLicenseInfo(map));
    }

    @PostMapping("obtainVerifyCode")
    public ResponseResult<Boolean> obtainVerifyCode(@RequestBody String phoneNum) {
        if (!RegexUtils.isMobile(phoneNum)) {
            throw new GenericException("手机号码格式不正确,请重新输入");
        }
        return ResponseResult.ok(this.smsService.obtainVerifyCode(phoneNum));
    }

    @PostMapping(value = "incoming", produces = MediaType.APPLICATION_XML_VALUE)
    public ResponseResult<MsgEntity> receivesWechatMessage(@RequestBody MsgEntity msgEntity) {
        log.info("接收微信服务器返回信息：{}", msgEntity);
        return ResponseResult.ok(msgEntity);
    }

    /**
     * @param userId
     * @return
     */
    @ApiOperation("查询优惠券的数量")
    @PostMapping("searchCountCouponByUserId")
    public ResponseResult<Integer> searchCountCouponByUserId(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycBaseService.searchCountCouponByUserId(claims.getId()));
    }

    /**
     * 依据类型分页查询用户拥有的优惠券
     * 
     * @param params
     * @return
     */
    @ApiOperation("依据类型分页查询用户拥有的优惠券")
    @PostMapping("searchCouponByUserIdAndType")
    public ResponseResult<PageInfo<Map<String, Object>>> searchCouponByUserIdAndType(@RequestBody Map<String, Object> params, @RequestHeader(name = EycConstants.TOKEN) String token) {
        params.put(EycConstants.USER_ID, JWTUtil.parseJWT(token).getId());
        return ResponseResult.ok(this.eycBaseService.searchCouponByUserIdAndType(params));
    }
    
    @ApiOperation("依据类型分页查询用户领取优惠券的金额")
    @PostMapping("sumCouponAmountByUserIdAndType")
    public ResponseResult<Integer> sumCouponAmountByUserIdAndType(@RequestBody Map<String, Object> params, @RequestHeader(name = EycConstants.TOKEN) String token) {
        params.put(EycConstants.USER_ID, JWTUtil.parseJWT(token).getId());
        return ResponseResult.ok(this.eycBaseService.sumCouponAmountByUserIdAndType(params));
    }

    @ApiOperation("获取用户信息")
    @PostMapping("searchEycUser")
    public ResponseResult<EycUser> searchEycUser(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.searchEycUserByUserIdAndUserType(claims.getId(), UserTypeEnums.OUTER_USER.getCode()));
    }

    @PostMapping("searchEycVehicleAvByPlateNum")
    public ResponseResult<EycVehicleAv> searchEycVehicleAvByPlateNum(@RequestBody String plateNum) {
        EycVehicleAv eycVehicleAv = this.eycBaseService.searchEycVehicleAvByPlateNum(plateNum);
        return ResponseResult.ok(eycVehicleAv);
    }

    /**
     * @param userId
     * @return
     */
    @ApiOperation("查询车辆列表")
    @PostMapping("searchEycVehicleFileByUserId")
    public ResponseResult<List<EycVehicleFile>> searchEycVehicleFileByUserId(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.searchEycVehicleFileByUserId(claims.getId()));
    }

    @ApiOperation("查询车辆列表")
    @PostMapping("searchEycVehicleFileCountByUserId")
    public ResponseResult<Integer> searchEycVehicleFileCountByUserId(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.searchEycVehicleFileCountByUserId(claims.getId()));
    }

    @PostMapping("searchInspectionStations")
    public ResponseResult<List<EycInspStation>> searchInspectionStations(@RequestBody Map<String, Object> params) {
        return ResponseResult.ok(this.eycService.searchEycInspectionStations(params));
    }

    @ApiOperation("查询优惠券的记录")
    @PostMapping("searchOneCouponByUserId")
    public ResponseResult<EycUserCoupon> searchOneCouponByUserId(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycBaseService.searchOneCouponByUserId(claims.getId()));
    }

    @PostMapping("searchOrders")
    public ResponseResult<PageInfo<Map<String, Object>>> searchOrders(@RequestBody Map<String, Object> params, @RequestHeader(name = EycConstants.TOKEN) String token) {
        params.put(EycConstants.USER_ID, JWTUtil.parseJWT(token).getId());
        return ResponseResult.ok(this.eycService.searchOrders(params));
    }

    @ApiOperation("查询未完成的订单订单数量")
    @PostMapping("searchUncompletedOrderCount")
    public ResponseResult<Integer> searchUncompletedOrderCount(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.searchUncompletedOrderCount(claims.getId()));
    }

    /**
     * @param eycOrder
     * @return
     */
    @ApiOperation("查询未支付的订单数量")
    @PostMapping("searchUnpaidOrderCount")
    public ResponseResult<Integer> searchUnpaidOrderCount(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.searchUnpaidOrderCount(claims.getId()));
    }

    @ApiOperation("节约现金")
    @PostMapping("sumSavingCapital")
    public ResponseResult<BigDecimal> sumSavingCapital(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.sumOrderPreferentialAmountByUserId(claims.getId()));
    }
    @ApiOperation("订单支付现金")
    @PostMapping("sumOrderPayAmountByUserId")
    public ResponseResult<BigDecimal> sumOrderPayAmountByUserId(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.sumOrderPayAmountByUserId(claims.getId()));
    }

    @ApiOperation("统计车辆价值")
    @PostMapping("sumVehicleAvAmount")
    public ResponseResult<BigDecimal> sumVehicleAvAmount(@RequestHeader(name = EycConstants.TOKEN) String token) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycBaseService.sumVehicleAvAmount(claims.getId()));
    }
    

    @PostMapping("searchEycVehicleFileByPlateNum")
    public ResponseResult<EycVehicleFile> searchEycVehicleFileByPlateNum(@RequestHeader(name = EycConstants.TOKEN) String token,@RequestBody String plateNum) {
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycService.searchEycVehicleFileByPlateNum(claims.getId(), plateNum));
    }

    @PostMapping("updateEycVehicleFile")
    public ResponseResult<EycVehicleFile> updateEycVehicleFile(@RequestBody EycVehicleFile eycVehicleFile) {
        return ResponseResult.ok(this.eycService.updateEycVehicleFile(eycVehicleFile));
    }
    
    @PostMapping("searchEycInspStationById")
    public ResponseResult<EycInspStation> searchEycInspStationById(@RequestBody String inspStationId) {
        return ResponseResult.ok(this.eycBaseService.searchEycInspStationById(inspStationId));
    }
    
    @PostMapping("searchEycOtherShopById")
    public ResponseResult<EycOtherShop> searchEycOtherShopById(@RequestBody String poiId) {
        return ResponseResult.ok(this.eycBaseService.searchEycOtherShopById(poiId));
    }
    
    @PostMapping("searchEycCouponRuleByTypeCde")
    public ResponseResult<List<Map<String, Object>>> searchEycCouponRuleByTypeCde(@RequestBody Map<String,Object> params) {
        return ResponseResult.ok(this.eycBaseService.searchEycCouponRuleByTypeCde(params));
    }

    @PostMapping("uploadVehicleLicense")
    public ResponseResult<String> uploadVehicleLicense(@RequestParam("filePath") String filePath, @RequestParam(value = "file") MultipartFile file) throws IOException {
        String fileNme = EycFileUtil.uploadFile(this.eycProperties.getFileDir() + filePath, file);
        return ResponseResult.ok(fileNme);
    }

    @GetMapping("verificationOrder")
    public ResponseResult<EycOrder> verificationOrder(String orderNum) {
        return ResponseResult.ok(this.eycService.verificationOrder(orderNum));
    }
    
    @PostMapping("searchVehicleTypeCategoryItemByTypeCde")
    public ResponseResult<List<EycCouponRule>> searchVehicleTypeCategoryItemByTypeCde(@RequestBody String typeCde){
        return ResponseResult.ok(this.eycBaseService.searchVehicleTypeCategoryItemByTypeCde(typeCde));
    }
    
    @PostMapping("searchSubTypeCategoryItemByTypeCde")
    public ResponseResult<List<EycCouponRule>> searchSubTypeCategoryItemByTypeCde(@RequestBody String typeCde){
        return ResponseResult.ok(this.eycBaseService.searchSubTypeCategoryItemByTypeCde(typeCde));
    }
    
    @PostMapping("receiveCoupon")
    public ResponseResult<EycUserCoupon> receiveCoupon(@RequestBody EycCouponRule eycCouponRule,@RequestHeader(name = EycConstants.TOKEN) String token){
        Claims claims = JWTUtil.parseJWT(token);
        EycUserCoupon eycUserCoupon=this.eycBaseService.receiveCoupon(eycCouponRule,claims.getId());
        return ResponseResult.ok(eycUserCoupon);
    }
    
    @PostMapping("receiveCoupons")
    public ResponseResult<Boolean> receiveCoupons(@RequestBody List<EycCouponRule> eycCouponRules,@RequestHeader(name = EycConstants.TOKEN) String token){
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycBaseService.receiveCoupons(eycCouponRules,claims.getId()));
    }
    
    @PostMapping("pay/obtainAuthorization")
    public String obtainAuthorization(@RequestHeader("Authorization") String token) {
        return "token is " + token;
    }
    
    @PostMapping("searchAppointedDayPickupCarNum")
    public ResponseResult<Integer> searchAppointedDayPickupCarNum(@RequestBody String appointmentDt){
        return ResponseResult.ok(this.eycService.searchAppointedDayPickupCarNum(appointmentDt));
    }
    
    @PostMapping("hasVerificationAuthority")
    public ResponseResult<List<EycVerPerson>> hasVerificationAuthority(@RequestHeader(name = EycConstants.TOKEN) String token){
        Claims claims = JWTUtil.parseJWT(token);
        return ResponseResult.ok(this.eycBaseService.hasVerificationAuthority(claims.getId()));
    }
}
